from . import config
import pandas as pd
import sys
sys.path.append(config.pj_root)
import steward as st
import pickle
import numpy as np
from IPython.display import clear_output


def test(X, info_df, use_model=config.model, use_fold_model=None):
    '''
    X_df: feature
    y_df : ['orderid', 'roomid']
    '''

    if use_fold_model is None:
        with open(config.pj_root + 'model/%s.mo' % use_model.__name__, 'rb') as f:
            model = pickle.load(f)
    else:
        with open(config.pj_root + 'model/%s-fold-%d.mo' % (use_model.__name__, use_fold_model), 'rb') as f:
            model = pickle.load(f)

    pred = model.predict_proba(X)[:, 1]
    table = info_df[['orderid', 'roomid']].join(pd.DataFrame(pred, index=info_df.index, columns=['pred_proba']))
    result = table.groupby('orderid').apply(lambda x: x[x.pred_proba == x.pred_proba.max()].iloc[0]['roomid'])
    result.name = 'predict_roomid'
    result = pd.DataFrame(result)
    result.to_csv(config.pj_root + 'result/ctrip_%s.csv' % (use_model.__name__))


def test_iters(X, info_df, use_model=config.model, use_fold_model=None):
    '''
    X_df: feature
    y_df : ['orderid', 'roomid']
    '''

    if use_fold_model is None:
        with open(config.pj_root + 'model/%s.mo' % use_model.__name__, 'rb') as f:
            model = pickle.load(f)
    else:
        with open(config.pj_root + 'model/%s-fold-%d.mo' % (use_model.__name__, use_fold_model), 'rb') as f:
            model = pickle.load(f)

    def iter_n_rows(X, n):
        len_row = X.shape[0]
        start = 0
        while start < len_row:
            if start + n >= len_row:
                yield X[start:]
                break
            else:
                yield X[start:start + n]
                start += n

    __pred = []
    n_iters = 100000
    len_row = X.shape[0]
    has_iter = 0
    last_rate = 5
    for i, row in enumerate(iter_n_rows(X, n_iters)):
        has_iter += n_iters
        rate = has_iter / len_row
        if rate * 100 > last_rate:
            print('%.2f%%' % (rate * 100))
            last_rate += 5
        __pred.append(model.predict_proba(row)[:, 1])

    pred = np.concatenate(__pred)

    table = info_df[['orderid', 'roomid']].join(pd.DataFrame(pred, index=info_df.index, columns=['pred_proba']))
    result = table.groupby('orderid').apply(lambda x: x[x.pred_proba == x.pred_proba.max()].iloc[0]['roomid'])
    result.name = 'predict_roomid'
    result = pd.DataFrame(result)
    result.to_csv(config.pj_root + 'result/ctrip_%s.csv' % (use_model.__name__))


def test_hdf5(f, feature_list, info_df, use_model=config.model, use_fold_model=None, use_cols_index=None,
              tag='', model_name=None, save_proba=False, save_result=True):
    assert save_proba or save_result
    if model_name is None:
        model_name = use_model.__name__ + '_' + tag
        model_file_name = config.pj_root + 'model/%s_%s.mo' % (use_model.__name__, tag)
    else:
        model_name = model_name + '_' + tag
        model_file_name = config.pj_root + 'model/' + model_name + '.mo'
    with open(model_file_name, 'rb') as model_f:
        model = pickle.load(model_f)
        print('use_model: ', model_file_name)

    __pred = []

    for i, X in enumerate(st.tools.iter_n_rows_list([f[name] for name in feature_list], 100000)):
        if use_cols_index is not None:
            X = X[:, use_cols_index]
        __pred.append(model.predict_proba(X)[:, 1])
        clear_output()
        print('%.2f%%...' % (i * 100000 / f[feature_list[0]].shape[0] * 100))
    clear_output()
    pred = np.concatenate(__pred)
    table = info_df[['orderid', 'roomid']].join(pd.DataFrame(pred, index=info_df.index, columns=['pred_proba']))
    if save_proba:
        table['pred_proba'].to_csv(config.pj_root + 'result/proba/ctrip_%s.csv' % (model_name), index=False)

    if save_result:
        print('now groupby to select max....')
        result = table.groupby('orderid').apply(lambda x: x[x.pred_proba == x.pred_proba.max()].iloc[0]['roomid'])
        result.name = 'predict_roomid'
        result = pd.DataFrame(result)
        result.to_csv(config.pj_root + 'result/ctrip_%s.csv' % (model_name))

    clear_output()
    print('ok!')


def test_hdf5_ensemble(f, feature_list, info_df, model_name_list, tag_list, weight_list, call_test_first=True):
    if call_test_first:
        for i, _ in enumerate(model_name_list):
            print(i + 1, 'model')
            test_hdf5(f, feature_list, info_df, model_name=model_name_list[i], tag=tag_list[i], save_result=False, save_proba=True)

    __all_pred = []
    for i, _ in enumerate(model_name_list):
        filename = config.pj_root + 'result/proba/ctrip_%s.csv' % (model_name_list[i] + '_' + tag_list[i])
        __all_pred.append(pd.read_csv(filename, header=-1).values[:, 0])  # 第一行不是列名！

    all_pred = pd.DataFrame(np.array(__all_pred).transpose())

    all_pred = all_pred.transform(lambda x: x.rank() / len(x), axis=0)

    final_pred = np.zeros(all_pred.shape[0])  # 加权和

    for i in range(all_pred.shape[1]):
        final_pred += weight_list[i] * all_pred.iloc[:, i]

    final_table = info_df[['orderid', 'roomid']].join(pd.DataFrame(final_pred, index=info_df.index, columns=['pred_proba']))

    resemble_name = []
    for i, _ in enumerate(model_name_list):
        resemble_name.append(model_name_list[i][:5] + '_' + tag_list[i] + '_wi' + str(weight_list[i]))
    resemble_name = '+'.join(resemble_name)

    print('now groupby to select max....')
    result = final_table.groupby('orderid').apply(lambda x: x[x.pred_proba == x.pred_proba.max()].iloc[0]['roomid'])
    result.name = 'predict_roomid'
    result = pd.DataFrame(result)
    result.to_csv(config.pj_root + 'result/ctrip_%s.csv' % (resemble_name))
    print('ok. check: ', 'result/ctrip_%s.csv' % (resemble_name))
